package mop.model.task.tasktype;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import mop.exception.IllegalDescriptionException;
import mop.exception.IllegalDuplicationException;
import mop.exception.IllegalIdException;
import mop.model.AbstractModelWithDescription;
import mop.model.DataBase;
import mop.model.resource.ResourceType;
import mop.model.task.field.Field;
import mop.model.task.field.FieldInterface;
import mop.model.user.User;
import mop.model.user.UserType;
import mop.security.acl.Acl;
import mop.security.acl.AssetInterface;
import mop.util.Couple;

/**
 * TaskType class
 *
 * @author MOP Team 7
 *
 * @invar Description is valid.
 *  	  @see AbstractDescriptionModel
 */
public class TaskType extends AbstractModelWithDescription implements TaskTypeInterface, AssetInterface
{

	/**
	 * Constructor for TaskType
	 *
	 * @param db 					The instance of the database where our tasktypes are kept
	 * @param id					The identifier of the tasktype
	 * @param description 			The description of the tasktype
	 * @param fields 				The fields that the Tasktype has
	 * @param resourceConstraints 	The ResourceTypes this TaskType needs
	 * @param acl					Acl with rights for this system
	 *
	 * @effect	(Tries to) set the description.
	 * 		| setDescription(description)
	 * @effect gets added to the database db
	 * @effect set usertypes
	 * 
	 * @post 
	 *
	 * @throws  IllegalDescriptionException
	 * 		Thrown when the Project description is invalid.
	 * @throws IllegalDuplicationException
	 * 		| user might be duplicate
	 * @throws IllegalIdException 
	 * 			Invalid identifier
	 */
	public TaskType(DataBase<TaskType> db, String id, String description,List<Field> fields,HashMap<ResourceType,Couple<Integer,Integer>> resourceConstraints,
			List<UserType> ownertypes) throws IllegalDescriptionException,IllegalDuplicationException, IllegalIdException
	{
		super(id,description);
		db.add(this);
		
		if(fields != null)
			this.fields.addAll(fields);
		
		this.resourceConstraints = resourceConstraints;
		this.acl = new Acl();
		setOwnerTypes(ownertypes);
	
	}


	/**
	 * Constructor that uses description as identifier
	 * @param db 			The instance of the database where our tasktypes are kept
	 * @param description 	the description of the tasktype
	 * @param fields 		The fields that the Tasktype has
	 * @param necessities 	The ResourceTypes this TaskType needs
	 * @param ownertypes 	The owner types for this Takstype
	 * 
	 * @effect	Call constructor with identifier
	 * 	|this(db,description,description,fields,necessities,ownertypes)
	 *
	 */
	public TaskType(DataBase<TaskType> db, String description, List<Field> fields, HashMap<ResourceType,Couple<Integer,Integer>> necessities,
			List<UserType> ownertypes) throws IllegalDescriptionException, IllegalDuplicationException, IllegalIdException{
		this(db,description,description,fields,necessities,ownertypes);
	}

	/***************************************************************************
	 * 						Fields
	 ***************************************************************************/

	/**
	 * Clone all fields and return m
	 *
	 * @return copy of fields list
	 */
	public List<Field> getFields()
	{
		LinkedList<Field> ret = new LinkedList<Field>();
		ret.addAll(fields);
		return ret;
	}

	/**
	 * Returns interfaces to copies of the fields.
	 *
	 * @return  List<FieldInterface>
	 */
	public List<FieldInterface> getFieldList()
	{
	    List<FieldInterface> f = new LinkedList<FieldInterface>();
	    f.addAll(this.getFields());
	    return f;
	}

	/** List containing fields */
	final List<Field> fields = new LinkedList<Field>();


	/***************************************************************************
	 * 						ResourceTypes
	 ***************************************************************************/
	
	/**
	 * Get Hashmap with resource constraints
	 */
	public HashMap<ResourceType,Couple<Integer,Integer>> getResourceConstraints(){
		HashMap<ResourceType,Couple<Integer,Integer>> result = new HashMap<ResourceType,Couple<Integer,Integer>>();
		result.putAll(resourceConstraints);
		return result;
	}
	
	/**
	 * Resource reservation constraints
	 */
	final HashMap<ResourceType,Couple<Integer,Integer>> resourceConstraints;

	/***************************************************************************
	 * 						Owner Types
	 ***************************************************************************/

	/**
	 * Check whether given user can create task of this type
	 * 
	 * @param u	User
	 *
	 * @return acl.isAllowed(u,this,'create');
	 */
	public boolean checkUserConstraints(User u)
	{
		return acl.isAllowed(u, this, "create");
	}
	
	/**
	 * Set the usertypes that can create task with given tasktype
	 * @param types
	 */
	private void setOwnerTypes(List<UserType> types){
		if(types == null || types.size() == 0){
			acl.allow(null,this,new String[]{"create"},null);
		}else{
			for(UserType type : types){
				acl.allow(type, this, new String[]{"create"}, null);
			}
		}
	}

	/** Acl for task type permissions */
	final Acl acl;

	/***************************************************************************
	 * 						Model interface
	 ***************************************************************************/


	/**
	 * get a reference to the interface
	 * @return this
	 */
	public TaskTypeInterface getInterface()
	{
		return this;
	}


	/**
	 * @see AssetInterface#getAssetId()
	 */
	@Override
	public String getAssetId() {
		return getId();
	}


}
